package com.example.demomap;

import java.util.ArrayList;
import java.util.List;

import javax.microedition.khronos.opengles.GL10;

import org.anddev.andengine.engine.Engine;
import org.anddev.andengine.engine.camera.Camera;
import org.anddev.andengine.engine.camera.hud.controls.BaseOnScreenControl;
import org.anddev.andengine.engine.camera.hud.controls.DigitalOnScreenControl;
import org.anddev.andengine.engine.camera.hud.controls.BaseOnScreenControl.IOnScreenControlListener;
import org.anddev.andengine.engine.handler.physics.PhysicsHandler;
import org.anddev.andengine.engine.options.EngineOptions;
import org.anddev.andengine.engine.options.EngineOptions.ScreenOrientation;
import org.anddev.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.anddev.andengine.entity.layer.tiled.tmx.TMXLayer;
import org.anddev.andengine.entity.layer.tiled.tmx.TMXProperties;
import org.anddev.andengine.entity.layer.tiled.tmx.TMXProperty;
import org.anddev.andengine.entity.layer.tiled.tmx.TMXTile;
import org.anddev.andengine.entity.layer.tiled.tmx.TMXTileProperty;
import org.anddev.andengine.entity.layer.tiled.tmx.TMXTiledMap;
import org.anddev.andengine.entity.scene.Scene;
import org.anddev.andengine.entity.scene.background.ColorBackground;
import org.anddev.andengine.entity.sprite.AnimatedSprite;
import org.anddev.andengine.entity.sprite.Sprite;
import org.anddev.andengine.entity.sprite.TiledSprite;
import org.anddev.andengine.entity.util.FPSLogger;
import org.anddev.andengine.input.touch.TouchEvent;
import org.anddev.andengine.opengl.texture.Texture;
import org.anddev.andengine.opengl.texture.TextureOptions;
import org.anddev.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.anddev.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.anddev.andengine.opengl.texture.region.TextureRegion;
import org.anddev.andengine.opengl.texture.region.TextureRegionFactory;
import org.anddev.andengine.opengl.texture.region.TiledTextureRegion;
import org.anddev.andengine.ui.activity.BaseGameActivity;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Point;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.Toast;

public class MainActivity extends BaseGameActivity {

    // ===========================================================
        // Constants
        // ===========================================================

		private static final int CAMERA_WIDTH = 480;
		private static final int CAMERA_HEIGHT = 320;

        // ===========================================================
        // Fields
        // ===========================================================

        private Camera mCamera;
        private BitmapTextureAtlas mTexture;
        private TiledTextureRegion mFaceTextureRegion;

        private BitmapTextureAtlas mOnScreenControlTexture;
        private TextureRegion mOnScreenControlBaseTextureRegion;
        private TextureRegion mOnScreenControlKnobTextureRegion;
        
        //Thêm code ở đoạn này
        private TMXTiledMap mTmxTiledMap;
        private TMXLayer VatCanTMXLayer;
        private String tenBanDo = "map2.tmx";

        @Override
        public Engine onLoadEngine() {
            this.mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
            
            return new Engine(new EngineOptions(true, ScreenOrientation.LANDSCAPE, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), this.mCamera));
        }

        @Override
        public void onLoadResources() {
        	BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");

            this.mTexture = new BitmapTextureAtlas(128, 128, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
            //this.mFaceTextureRegion = TextureRegionFactory.createFromAsset(this.mTexture, this, "hero.png", 0, 0);
            this.mFaceTextureRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mTexture, this, "hero.png", 0, 0, 3, 4);
            
            this.mOnScreenControlTexture = new BitmapTextureAtlas(256, 128, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
            this.mOnScreenControlBaseTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mOnScreenControlTexture, this, "onscreen_control_base.png", 0, 0);
            this.mOnScreenControlKnobTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mOnScreenControlTexture, this, "onscreen_control_knob.png", 128, 0);
        	
            this.mEngine.getTextureManager().loadTextures(this.mTexture, this.mOnScreenControlTexture);
        }

        
        public static Point posCurrent = new Point(1,2);
        public static Direction curDirection = Direction.DOWN;
        @Override
        public Scene onLoadScene() {
            this.mEngine.registerUpdateHandler(new FPSLogger());

            final Scene scene = new Scene();
            scene.setBackground(new ColorBackground(0.09804f, 0.6274f, 0.8784f));
           
            //Tải map
            Log.v("","hehe");
            mTmxTiledMap = TaiBanDo.getTMXTiledMap(scene, mEngine, this, tenBanDo, this);
            // Lấy layer vật cản từ đối tượng mTMXTiledrMap
            ArrayList<TMXLayer> mapLayers = mTmxTiledMap.getTMXLayers();
            for(TMXLayer layer : mapLayers){
                //Nếu có layer nào tên như là "tuong" sẽ được lấy
                if(layer.getName().equals("block")){
                    VatCanTMXLayer = layer;
                }
                //Thêm vào cảnh trò chơi
                scene.attachChild(layer);
            }
            
            final TiledSprite face = new TiledSprite(32, 32, this.mFaceTextureRegion);
            final PhysicsHandler physicsHandler = new PhysicsHandler(face);
            face.setCurrentTileIndex(1, 2);
            face.registerUpdateHandler(physicsHandler);
            
            scene.attachChild(face);

            final DigitalOnScreenControl digitalOnScreenControl = new DigitalOnScreenControl(0, CAMERA_HEIGHT - this.mOnScreenControlBaseTextureRegion.getHeight(), this.mCamera, this.mOnScreenControlBaseTextureRegion, this.mOnScreenControlKnobTextureRegion, 0.1f, new IOnScreenControlListener() {
                @Override
                public void onControlChange(final BaseOnScreenControl pBaseOnScreenControl, final float pValueX, final float pValueY) {
                	
                    //Nếu bộ điều khiển nghiên về 1 trong 4 hướng
                    if(pValueX != 0 || pValueY != 0){
                    	Direction dir = getDirection(pValueX,pValueY);
                    	
                    	List<Point> ptNextCell = NextCell(face,dir);

                    	boolean check = false;
                    	int sum = 0;
                    	for (int i=0;i<ptNextCell.size();i++)
                    	{
	                        //Dùng tâm của Sprite này để kiểm tra xem có va chạm với vật cản hay ko
	                        TMXTile mTMXTile = VatCanTMXLayer.getTMXTileAt(ptNextCell.get(i).x,ptNextCell.get(i).y);
	                        
	                        //Đoạn code này kiểm tra va chạm nè
	                        try{
	                            if(mTMXTile != null){
	                                TMXProperties<TMXTileProperty> mTMXProperties = mTMXTile.getTMXTileProperties(mTmxTiledMap);
	                                TMXProperty mTmxProperty = mTMXProperties.get(0);
	                                if(mTmxProperty.getName().equals("block")){
	                                    Log.v("", "Chạm phải vật cản rồi !!!");
	                                }
	                            }
	                        }catch(Exception e){
	                            Log.v("", "Không có vật cản !!!");
	                            sum++;
	                        }
                    	}
                    	if (sum == ptNextCell.size())
                    		check = true;
                    	if (check)
                    	{
                    		Point ptNew = NextMove(face,dir);
                            face.setPosition(ptNew.x,ptNew.y);
                            changeCamera(face,pValueX,pValueY);
                    	}
                    }                   
                    //physicsHandler.setVelocity(pValueX * 200, pValueY * 100);
                }
            });
            digitalOnScreenControl.getControlBase().setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
            digitalOnScreenControl.getControlBase().setAlpha(0.5f);
            digitalOnScreenControl.getControlBase().setScaleCenter(0, 128);
            digitalOnScreenControl.getControlBase().setScale(1.25f);
            digitalOnScreenControl.getControlKnob().setScale(1.25f);
            digitalOnScreenControl.refreshControlKnobPosition();

            scene.setChildScene(digitalOnScreenControl);
            return scene;
        }
        @Override
        public void onLoadComplete() {

        }
        public int getRow(Direction dir)
        {
        	if (dir == Direction.UP)
        		return 0;
        	else if (dir == Direction.RIGHT)
        		return 1;
        	else if (dir == Direction.DOWN)
        		return 2;
        	else
        		return 3;
        }
        public void changeTiled(TiledSprite fac)
        {
        	fac.setCurrentTileIndex(posCurrent.x,posCurrent.y);
        }
        public Point NextMove(TiledSprite fac, Direction dir)
        {
        	int newRow = getRow(dir);
        	if (dir != curDirection)
        	{
        		posCurrent.y = newRow;
        		changeTiled(fac);
        	}
        	else
        	{
        		posCurrent.x = (posCurrent.x == 2) ? 0 : (posCurrent.x+1);
        		changeTiled(fac);
        	}
        	curDirection = dir;
        	int posX = (int)fac.getX();
        	int posY = (int)fac.getY();
        	if (dir == Direction.UP)
        		posY = posY - 16;
        	else if (dir == Direction.DOWN)
        		posY = posY + 16;
        	else if (dir == Direction.RIGHT)
        		posX = posX + 16;
        	else
        		posX = posX - 16;
        	Point pt = new Point(posX,posY);
        	return pt;
        }
        
        public List<Point> NextCell(TiledSprite fac, Direction dir)
        {
        	List<Point> listPt = new ArrayList<Point>();
        	int posX = (int)fac.getX();
        	int posY = (int)fac.getY();
        	if (dir == Direction.UP)
        		posY = posY - 32;
        	else if (dir == Direction.DOWN)
        		posY = posY + 32;
        	else if (dir == Direction.RIGHT)
        		posX = posX + 32;
        	else
        		posX = posX - 32;
        	posX += 16;
        	posY += 16;
        	Point pt = new Point(posX,posY);
        	if (dir == Direction.DOWN)
        		pt.y = posY - 1;
        	else if (dir == Direction.RIGHT)
        		pt.x = posX - 1;
        	listPt.add(pt);
        	if (((dir == Direction.UP || dir == Direction.DOWN) && fac.getX() % 32 != 0)
        		|| ((dir == Direction.LEFT || dir == Direction.RIGHT) && fac.getY() % 32 != 0))
        	{
        	if (fac.getX() % 32 != 0 || fac.getY() % 32 != 0)
        	{
	        	if (dir == Direction.UP || dir == Direction.DOWN)
	        		posX = posX - 1;
	        	else if (dir == Direction.RIGHT || dir == Direction.LEFT)
	        		posY = posY -1;
	        	pt = new Point(posX,posY);
	        	listPt.add(pt);
        	}
        	}
        	return listPt;
        }
        final int CAMERA_HERO_WIDTH = 288;
        final int CAMERA_HERO_HEIGHT = 192;
        public boolean IsInArea(TiledSprite fac)
        {
        	int ctX = (int)MainActivity.this.mCamera.getCenterX();
        	int ctY = (int)MainActivity.this.mCamera.getCenterY();
        	int top = ctY - CAMERA_HERO_HEIGHT/2;
			int bottom = ctY + CAMERA_HERO_HEIGHT/2;
			int right = ctX + CAMERA_HERO_WIDTH/2;
			int left = ctX - CAMERA_HERO_WIDTH/2;
			if (fac.getX() > left && fac.getX() < right && fac.getY() > top && fac.getY() < bottom)
				return true;
        	return false;
        }
        public enum Direction
        {
        	UP,
        	RIGHT,
        	DOWN,
        	LEFT
        }
        public Direction getDirection(double x,double y)
        {
        	if (x == 1)
        		return Direction.RIGHT;
        	else if (x == -1)
        		return Direction.LEFT;
        	else if (y == -1)
        		return Direction.UP;
        	else
        		return Direction.DOWN;
        }
        public boolean GoFar(Direction dir, TiledSprite fac)
        {
        	int ctX = (int)MainActivity.this.mCamera.getCenterX();
        	int ctY = (int)MainActivity.this.mCamera.getCenterY();
        	int top = ctY - CAMERA_HERO_HEIGHT/2;
			int bottom = ctY + CAMERA_HERO_HEIGHT/2;
			int right = ctX + CAMERA_HERO_WIDTH/2;
			int left = ctX - CAMERA_HERO_WIDTH/2;
        	if (dir == Direction.UP)
        	{
        		if ((int)fac.getY() < top)
        			return true;
        	}
        	else if (dir == Direction.DOWN)
        	{
        		if ((int)fac.getY() > bottom)
        			return true;
        	}
        	else if (dir == Direction.RIGHT)
        	{
        		if ((int)fac.getX() > right)
        			return true;
        	}
        	else if (dir == Direction.LEFT)
        	{
        		if ((int)fac.getX() < left)
        			return true;
        	}
        	return false;
        }
        public void changeCamera(TiledSprite fac,double x, double y)
        {
        	if (!IsInArea(fac))
        	{
        		Direction dir = getDirection(x,y);
        		if (GoFar(dir,fac))
        		{
		        	if (x == 1 && MainActivity.this.mCamera.getCenterX() < 752)
		        		MainActivity.this.mCamera.offsetCenter(32, 0);
			    	else if (x == -1 && MainActivity.this.mCamera.getCenterX() > 240)
			    		MainActivity.this.mCamera.offsetCenter(-32, 0);
			    	else if (y == 1 && MainActivity.this.mCamera.getCenterY() < 256)
			    		MainActivity.this.mCamera.offsetCenter(0, 32);
			    	else if (y == -1 && MainActivity.this.mCamera.getCenterY() > 160)
			    		MainActivity.this.mCamera.offsetCenter(0, -32);
        		}
        	}
        }
}